package com.pro.common.service.admin.controller;

import com.pro.common.api.enums.EnumSysRole;
import com.pro.common.api.exception.BusinessException;
import com.pro.common.api.model.ILoginInfo;
import com.pro.common.service.service.EnumAuthDict;
import com.pro.common.service.util.I18nUtils;
import com.pro.framework.api.util.AssertUtil;
import io.swagger.v3.oas.annotations.Parameter;
import org.apache.commons.io.input.ReversedLinesFileReader;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/log")
public class LogController {
    private static String logDir;
    // 只允许访问这些文件，避免路径穿越
    private static final Set<String> ALLOWED_LOG_FILES = Set.of(
            "admin.log",
            "goods-collect.log",
            "sync.log",
            "goods-launch-shein.log",
            "goods-launch-temu.log",
            "goods-launch-tiktok.log",
            "pay.log",
            "user.log",
            "goods-order.log",
            "shop.log",
            "site-content.log"
    );

    /**
     * 获取日志最后N行内容（默认2000行）
     */
    @GetMapping("/view")
    public ResponseEntity<String> viewLog(
            @RequestParam String filename,
            @RequestParam(defaultValue = "2000") int lines
            , @Parameter(hidden = true) ILoginInfo loginInfo
    ) throws IOException {
        logDir = EnumAuthDict.LOG_DIR.getValueCacheOrDefault("");
        EnumSysRole sysRole = loginInfo.getSysRole();
        AssertUtil.isTrue(EnumSysRole.ADMIN.equals(sysRole), "暂无权限");
        if (!ALLOWED_LOG_FILES.contains(filename)) {
            throw new BusinessException("非法日志文件名_", filename);
        }

        File logFile = new File(logDir, filename);
        if (!logFile.exists()) {
            return ResponseEntity.ok(I18nUtils.get("文件不存在_", filename));
//            return ResponseEntity.ok("");
//            throw new BusinessException("文件不存在_", filename);
        }

        List<String> linesList = tail(logFile, lines);
        return ResponseEntity.ok(String.join("\n", linesList));
    }

    /**
     * 下载完整日志文件
     */
    @GetMapping("/download")
    public ResponseEntity<Resource> downloadLog(@Parameter(hidden = true) ILoginInfo loginInfo, @RequestParam String filename) throws IOException {
        EnumSysRole sysRole = loginInfo.getSysRole();
        AssertUtil.isTrue(EnumSysRole.ADMIN.equals(sysRole), "暂无权限");
        // 白名单校验
        if (!ALLOWED_LOG_FILES.contains(filename)) {
            return ResponseEntity.badRequest().build();
        }
        logDir = EnumAuthDict.LOG_DIR.getValueCacheOrDefault("");
        File file = new File(logDir, filename);

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"")
                .contentLength(file.length())
                .body(new InputStreamResource(new FileInputStream(file)));

    }


    /**
     * 获取最后N行日志内容
     */
    private List<String> tail(File file, int numLines) throws IOException {
        List<String> result = new ArrayList<>();
        try (ReversedLinesFileReader reader = new ReversedLinesFileReader(file, StandardCharsets.UTF_8)) {
            String line;
            int count = 0;
            while ((line = reader.readLine()) != null && count < numLines) {
                result.add(line);
                count++;
            }
        }
        Collections.reverse(result); // 保持原始顺序
        return result;
    }
}
